﻿using System.Collections.Generic;
using ExpressionEngine.AggregateFunctions;

namespace ExpressionEngine
{
    /// <summary>
    /// Allows to evaluate expression with aggregate functions
    /// </summary>
    public class AggregateExpressionEvaluator: ExpressionEveluator
    {
        private List<BaseAggregateFunction> _aggregatedFunction = new List<BaseAggregateFunction>(new BaseAggregateFunction[]{
            new Sum(), new Average(), new Max(), new Min(), new Count()
        });

        /// <summary>
        /// Initializes a new instance of the ExpressionEngine.AggregateExpressionEvaluator class using the
        /// specified expression.
        /// </summary>
        /// <param name="expression">Aggregative expression</param>
        public AggregateExpressionEvaluator(string expression)
            : base(expression)
        {
            _aggregatedFunction.ForEach(f => f.LoadEntries(expression));
        }

        /// <summary>
        /// Resets the state of aggregative functions in expression
        /// </summary>
        public void Reset()
        {
            _aggregatedFunction.ForEach(f => f.Reset());
        }

        /// <summary>
        /// Adds values from the new row to aggregate function states
        /// </summary>
        /// <param name="valueProvider">allows expression evaluator to access fields of current row</param>
        public void RowChanged(IValueProvider valueProvider)
        {
            _aggregatedFunction.ForEach(f => f.RowChanged(valueProvider));
        }

        /// <summary>
        /// Returns result of evaluation
        /// </summary>
        /// <returns>evaluation result</returns>
        public double GetResult()
        {
            foreach (BaseAggregateFunction func in _aggregatedFunction)
            {
                Expression = func.ApplyEntries(Expression);
            }
            
            return Evaluate(null);
        }
    }
}
